package com.magenta.maxoptra.geocoding.geobase.webservice;

import com.magenta.maxoptra.gis.commons.Logger;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

/**
 * Project: Santa-cruz
 * Author:  Irina Isaeva
 * Created: 07.06.12 11:24
 * <p/>
 * Copyright (c) 1999-2012 Magenta Corporation Ltd. All Rights Reserved.
 * Magenta Technology proprietary and confidential.
 * Use is subject to license terms.
 * <p/>
 * $Id$
 */
public abstract class ObjectPool<T> {
    private static final Logger LOG = new Logger(ObjectPool.class);

    private Set<T> locked;
    private Queue<T> available;
    private String poolName;

    public ObjectPool() {
        this("");
    }

    protected ObjectPool(String poolName) {
        locked = new HashSet<T>();
        available = new LinkedList<T>();
        this.poolName = poolName;
    }

    private void log(String msg) {
        final int lockedSize = locked.size();
        final int availableSize = available.size();
        LOG.info(String.format("%s. Pool size: %d, available: %d, locked: %d",
                msg, lockedSize + availableSize, availableSize, lockedSize));
    }

    protected abstract T create();

    public synchronized T checkOut() {
        T t = available.poll();
        if (t == null) {
            t = create();
            log(String.format("Create new %s in " + poolName + " pool", t.getClass().getSimpleName()));
        }
        locked.add(t);
        return t;
    }

    public synchronized void invalidate(T t) {
        if (unlock(t)) {
            log(String.format("Invalidate %s in " + poolName + " pool", t.getClass().getSimpleName()));
        }
    }

    private boolean unlock(T t) {
        return t != null && locked.remove(t);
    }

    public synchronized void checkIn(T t) {
        if (unlock(t)) {
            available.add(t);
        }
    }

}


